<?php

namespace common\i18n;

use Yii;
use common\helpers\Html;
use common\helpers\StringHelper;
use common\helpers\ArrayHelper;
use DateTime;
use DateInterval;
use DateTimeZone;

/**
 * Formatter provides a set of commonly used data formatting methods.
 *
 * @author emhome <emhome@163.com>
 * @since 1.0
 */
class Formatter extends \yii\i18n\Formatter {

    /**
     * @var string the text to be displayed when formatting a `null` value.
     * Defaults to `'<span class="not-set">(not set)</span>'`, where `(not set)`
     * will be translated according to [[locale]].
     */
    public $imageNullDisplay;

    /**
     * Formats the value as an image tag.
     * @param mixed $value the value to be formatted.
     * @param array $options the tag options in terms of name-value pairs. See [[Html::img()]].
     * @return string the formatted result.
     */
    public function asImage($value, $options = []) {
        $cdn = true;
        $default = ArrayHelper::remove($options, 'default');
        if (!$value) {
            $value = $default ?: $this->imageNullDisplay;
            $cdn = false;
        }
        return Html::img($value, ArrayHelper::merge([
            'class' => 'cell-thumb-small',
            'alt' => $value
        ], $options), $cdn);
    }

    /**
     * Formats the value as an image tag.
     * @param mixed $value the value to be formatted.
     * @param array $options the tag options in terms of name-value pairs. See [[Html::img()]].
     * @return string the formatted result.
     */
    public function asGallery($value, $options = []) {
        $cdn = true;
        $default = ArrayHelper::remove($options, 'default');
        if (!$value) {
            $value = $default ?: $this->imageNullDisplay;
            $cdn = false;
        }
        if (!$value) {
            $cdn = false;
            $value = '@web/themes/images/undefind.jpg';
        }
        if ($cdn !== false) {
            $value = \common\helpers\Url::attach($value);
        }
        $img = Html::img($value, ArrayHelper::merge([
            'class' => 'cell-thumb-small',
            'alt' => $value
        ], $options), $cdn);
        return Html::a($img, $value, [
            'data-magnify' => 'gallery',
        ]);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asMaskMobile($value) {
        if ($value === null) {
            return $this->nullDisplay;
        }
        if ($value) {
            return StringHelper::maskChar($value, 3, 4);
        }
        return '-';
    }

    /**
     * Formats the value as masked an I.D.card number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asMaskIDCard($value) {
        if ($value === null) {
            return $this->nullDisplay;
        }
        if ($value) {
            return StringHelper::maskChar($value, 6, 4);
        }
        return '-';
    }

    /**
     * Formats the value as masked an I.D.card number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asMobile($value) {
        if ($value === null) {
            return $this->nullDisplay;
        }
        if (strlen($value) > 11) {
            /* @var $security \common\base\Security */
            $security = Yii::$app->security;
            return $security->decryptMaster($value);
        }
        return $value;
    }

    /**
     * Formats the value as masked an I.D.card number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asIdcardno($value) {
        if ($value === null) {
            return $this->nullDisplay;
        }
        if (strlen($value) > 18) {
            /* @var $security \common\base\Security */
            $security = Yii::$app->security;
            return $security->decryptMaster($value);
        }
        return $value;
    }

    /**
     * Formats the value as masked an I.D.card number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asColor($value) {
        return Html::colorBox($value);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asGender($value) {
        $genders = [
            '-',
            '男',
            '女',
        ];
        $gender = ArrayHelper::getValue($genders, $value);
        if (!$gender) {
            return $this->nullDisplay;
        }
        return $gender;
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asList($value) {
        if (empty($value)) {
            return $this->nullDisplay;
        }
        return Html::tag('ol', '<li>' . implode("</li><li>", $value) . '</li>', ['class' => 'breadcrumb']);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asStat($value) {
        return $this->asDecimal(count($value));
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asRegion($value) {
        if (empty($value) || !($value instanceof \common\db\RegionInterface)) {
            return $this->nullDisplay;
        }
        return Html::title($value->getRegionText(), $value->getAddressDetail());
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asTags($value) {
        if (empty($value)) {
            return $this->nullDisplay;
        }
        return Html::tag('ul', '<li>' . implode("</li><li>", $value) . '</li>', ['class' => 'tags']);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asLabel($value) {
        if (empty($value)) {
            return $this->nullDisplay;
        }
        return print_r($value, true);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asStars($value, $options = []) {
        $nums = (int) $value;
        $items = '';
        for ($i = 0; $i < 5; $i++) {
            $items .= '<li class="' . ($i < $nums ? 'active' : '') . '"></li>';
        }
        return Html::tag('ol', $items, ['class' => 'rate-stars']);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asDescription($value, $options = []) {
        if (empty($value)) {
            return $this->nullDisplay;
        }
        $string = StringHelper::truncate($value, 30);

        return Html::tag('div', $string, ['class' => 'description']);
    }

    /**
     * Formats the value as masked a mobile number tag.
     * This method simply returns back the parameter without any format.
     * The only exception is a `null` value which will be formatted using [[nullDisplay]].
     * @param mixed $value the value to be formatted.
     * @return string the formatted result.
     */
    public function asCountdown($value) {
        if ($value === null) {
            return $this->nullDisplay;
        }
        $hour = 0;
        $minute = 0;
        $second = 0;
        if ($value > 0) {
            $hour = floor($value / 3600);
            $minute = floor(($value - 3600 * $hour) / 60);
            $second = floor((($value - 3600 * $hour) - 60 * $minute) % 60);
        }
        return str_pad($hour, 2, 0, STR_PAD_LEFT) . ':' .
        str_pad($minute, 2, 0, STR_PAD_LEFT) . ':' .
        str_pad($second, 2, 0, STR_PAD_LEFT);
    }

    /**
     * Formats the value as an image tag.
     * @param mixed $value the value to be formatted.
     * @param array $options the tag options in terms of name-value pairs. See [[Html::img()]].
     * @return string the formatted result.
     */
    public function asUser($value, $options = ['class' => 'cell-thumb-small']) {
        if (empty($value) || !($value instanceof \common\base\BaseUser)) {
            return $this->nullDisplay;
        }
        return Html::userPorlet($value->getUserName(), $value->getPortrait(), $value->getExtends(), ArrayHelper::merge([
            'class' => 'cell-thumb-small',
            'url' => ['/user/default/view', 'id' => $value->id],
        ], $options));
    }

    /**
     * Formats the value as an image tag.
     * @param mixed $value the value to be formatted.
     * @param array $options the tag options in terms of name-value pairs. See [[Html::img()]].
     * @return string the formatted result.
     */
    public function asPolert($value, $options = ['class' => 'cell-thumb-small']) {
        if (!$value) {
            return Html::img($this->imageNullDisplay, $options);
        }
        if (empty($value) || !($value instanceof \common\base\BaseUser)) {
            return $this->nullDisplay;
        }
        $scheme = parse_url($value, PHP_URL_SCHEME);
        if ($scheme !== null) {
            if ($scheme == 'http') {
                $remoteExists = \common\helpers\Curl::checkRemoteFileExists($value);
                if (!$remoteExists) {
                    $value = $this->imageNullDisplay;
                }
            }
        } else {
            $value = Yii::getAlias('@attachUrl') . $value;
        }
        return parent::asImage($value, $options);
    }

    public function asDateDiff($value, $referenceTime = null, $absolute = false) {
        if ($value === null) {
            return $this->nullDisplay;
        }
        if ($value instanceof DateInterval) {
            $interval = $value;
        } else {
            $timestamp = $this->normalizeDatetimeValue($value);
            if ($timestamp === false) {
                // $value is not a valid date/time value, so we try
                // to create a DateInterval with it
                try {
                    $interval = new DateInterval($value);
                } catch (\Exception $e) {
                    // invalid date/time and invalid interval
                    return $this->nullDisplay;
                }
            } else {
                $timeZone = new DateTimeZone($this->timeZone);
                if ($referenceTime === null) {
                    $dateNow = new DateTime('now', $timeZone);
                } else {
                    $dateNow = $this->normalizeDatetimeValue($referenceTime);
                    $dateNow->setTimezone($timeZone);
                }
                $dateThen = $timestamp->setTimezone($timeZone);

                if ($absolute) {
                    $interval = $dateThen->diff($dateNow);
                } else {
                    $format = 'Y-m-d';
                    $_dateNow = date_create($dateNow->format($format));
                    $_dateThen = date_create($dateThen->format($format));
                    $interval = date_diff($_dateNow, $_dateThen);
                }
            }
        }
        return $interval->days;
    }

}
